package client.visualisator;

import java.awt.BorderLayout;
import java.awt.GraphicsConfiguration;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.FileNotFoundException;
import java.rmi.RemoteException;

import javax.media.j3d.Alpha;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Geometry;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.vecmath.AxisAngle4d;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

import org.jdesktop.j3d.loaders.vrml97.VrmlLoader;

import server.object.*;
import wiiremotej.WiiRemote;

import client.behavior.WiimoteManager;
import client.object.PObject3D;

import com.sun.j3d.loaders.IncorrectFormatException;
import com.sun.j3d.loaders.ParsingErrorException;
import com.sun.j3d.loaders.Scene;
import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.SimpleUniverse;


public class UniverseVisualisator extends JFrame {

	private static final long serialVersionUID = 900471231639282881L;

	private SimpleUniverse universe;
	
	private Canvas3D canvas;
	private BranchGroup scene;
	
	private JButton upButton;
	private JButton downButton;
	private JButton forwardButton;
	private JButton backwardButton;
	private JButton leftStepButton;
	private JButton rightStepButton;
	private JButton rotationHPlusButton;
	private JButton rotationHMinusButton; 
	private JButton rotationPPlusButton;
	private JButton rotationPMinusButton;
	private JButton rotationRPlusButton;
	private JButton rotationRMinusButton; 
	
	private BehaviorUpMouseListener behaviorUpMouseListener;
	private BehaviorDownMouseListener behaviorDownMouseListener;
	private BehaviorForwardMouseListener behaviorForwardMouseListener;
	private BehaviorBackwardMouseListener behaviorBackwardMouseListener;
	private BehaviorLeftStepMouseListener behaviorLeftStepMouseListener;
	private BehaviorRightStepMouseListener behaviorRightStepMouseListener;
	private BehaviorRotationHPlusMouseListener behaviorRotationHPlusMouseListener;
	private BehaviorRotationHMinusMouseListener behaviorRotationHMinusMouseListener;
	private BehaviorRotationPPlusMouseListener behaviorRotationPPlusMouseListener;
	private BehaviorRotationPMinusMouseListener behaviorRotationPMinusMouseListener;
	private BehaviorRotationRPlusMouseListener behaviorRotationRPlusMouseListener;
	private BehaviorRotationRMinusMouseListener behaviorRotationRMinusMouseListener;

	private JButton addButton;
	
	public UniverseVisualisator() {
		JPanel buttonsPanel = new JPanel();
		buttonsPanel.setLayout(new GridLayout(13, 1));
		
		upButton = new JButton("Up");
		downButton = new JButton("Down");
		forwardButton = new JButton("Forward");
		backwardButton = new JButton("Backward");
		leftStepButton = new JButton("Left");
		rightStepButton = new JButton("Right");
		rotationHPlusButton = new JButton("H+");
		rotationHMinusButton = new JButton("H-"); 
		rotationPPlusButton = new JButton("P+");
		rotationPMinusButton = new JButton("P-");
		rotationRPlusButton = new JButton("R+");
		rotationRMinusButton = new JButton("R-");
		
		buttonsPanel.add(upButton);
		buttonsPanel.add(downButton);
		buttonsPanel.add(forwardButton);
		buttonsPanel.add(backwardButton); 	
		buttonsPanel.add(leftStepButton);
		buttonsPanel.add(rightStepButton);
		buttonsPanel.add(rotationHPlusButton);
		buttonsPanel.add(rotationHMinusButton);
		buttonsPanel.add(rotationPPlusButton);
		buttonsPanel.add(rotationPMinusButton);
		buttonsPanel.add(rotationRPlusButton);
		buttonsPanel.add(rotationRMinusButton);
		
		behaviorUpMouseListener = new BehaviorUpMouseListener();
		upButton.addMouseListener(behaviorUpMouseListener);
		
		behaviorDownMouseListener = new BehaviorDownMouseListener();
		downButton.addMouseListener(behaviorDownMouseListener);
		
		behaviorForwardMouseListener = new BehaviorForwardMouseListener();
		forwardButton.addMouseListener(behaviorForwardMouseListener);
		
		behaviorBackwardMouseListener = new BehaviorBackwardMouseListener();
		backwardButton.addMouseListener(behaviorBackwardMouseListener);
		
		behaviorLeftStepMouseListener = new BehaviorLeftStepMouseListener();
		leftStepButton.addMouseListener(behaviorLeftStepMouseListener);
		
		behaviorRightStepMouseListener = new BehaviorRightStepMouseListener();
		rightStepButton.addMouseListener(behaviorRightStepMouseListener);
		
		behaviorRotationHPlusMouseListener = new BehaviorRotationHPlusMouseListener();
		rotationHPlusButton.addMouseListener(behaviorRotationHPlusMouseListener);
		
		behaviorRotationHMinusMouseListener = new BehaviorRotationHMinusMouseListener();
		rotationHMinusButton.addMouseListener(behaviorRotationHMinusMouseListener);
		
		behaviorRotationPPlusMouseListener = new BehaviorRotationPPlusMouseListener();
		rotationPPlusButton.addMouseListener(behaviorRotationPPlusMouseListener);
		
		behaviorRotationPMinusMouseListener = new BehaviorRotationPMinusMouseListener();
		rotationPMinusButton.addMouseListener(behaviorRotationPMinusMouseListener);
		
		behaviorRotationRPlusMouseListener = new BehaviorRotationRPlusMouseListener();
		rotationRPlusButton.addMouseListener(behaviorRotationRPlusMouseListener);
		
		behaviorRotationRMinusMouseListener = new BehaviorRotationRMinusMouseListener();
		rotationRMinusButton.addMouseListener(behaviorRotationRMinusMouseListener);
		
		behaviorRightStepMouseListener = new BehaviorRightStepMouseListener();
		rightStepButton.addMouseListener(behaviorRightStepMouseListener);
		
		getContentPane().setLayout(new BorderLayout());
		
		getContentPane().add(buttonsPanel, BorderLayout.WEST);

		setTitle("Visualisateur");
		init();
	}
	
	private void init() {
		GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();

		canvas = new Canvas3D(config);
		getContentPane().add(canvas, BorderLayout.CENTER);
		
		// Create a simple scene and attach it to the virtual universe
		universe = new SimpleUniverse (canvas) ;
		scene = createSceneGraph () ;
		
		scene.setCapability(BranchGroup.ALLOW_DETACH);
		scene.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
		scene.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
		scene.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);

		// cr�ation d'un navigateur
		TransformGroup vpTrans = universe.getViewingPlatform ().getViewPlatformTransform () ;
		KeyNavigatorBehavior keyNavBeh = new KeyNavigatorBehavior (vpTrans) ;
		keyNavBeh.setSchedulingBounds (new BoundingSphere (new Point3d (), 1000.0)) ;
		scene.addChild (keyNavBeh) ;

		// This will move the ViewPlatform back a bit so the
		// objects in the scene can be viewed.
		universe.getViewingPlatform ().setNominalViewingTransform () ;
		universe.addBranchGraph (scene) ;
		

	}
	
	public void compile(){
		// Have Java 3D perform optimizations on this scene graph.
		scene.compile () ;
		
	}
	
	public TransformGroup createColorCube (Vector3d v3d) {
		Transform3D translation = new Transform3D () ;
		translation.setTranslation (v3d) ;
		TransformGroup objTrans = new TransformGroup (translation) ;
		objTrans.setCapability (TransformGroup.ALLOW_TRANSFORM_WRITE) ;
		objTrans.setCapability (TransformGroup.ALLOW_TRANSFORM_READ) ;
		objTrans.setCapability (TransformGroup.ENABLE_PICK_REPORTING) ;
		// Create a simple Shape3D node; add it to the scene graph.
		ColorCube cc = new ColorCube (0.2) ;
		cc.getGeometry ().setCapability (Geometry.ALLOW_INTERSECT) ;
		objTrans.addChild (cc) ;
		return (objTrans) ;
	}

	public BranchGroup createSceneGraph () {
		// Create the root of the branch graph
		BranchGroup objRoot = new BranchGroup () ;
		//objRoot.addChild (createColorCube (new Vector3d (0, -0.5, 0))) ;
		//objRoot.addChild (createColorCube (new Vector3d (-0.5, -0.5, 0))) ;
		//objRoot.addChild (createColorCube (new Vector3d (0.5, -0.5, 0))) ;
		//objRoot.addChild (createColorCube (new Vector3d (0, 0, 0))) ;
		return objRoot ;
	}
	
	class BehaviorUpMouseListener implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			goLocallyInThisDirection(0, 0.1, 0);
		}

	}
	
	class BehaviorDownMouseListener implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			goLocallyInThisDirection(0, -0.1, 0);
		}

	}
	
	class BehaviorForwardMouseListener implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			goLocallyInThisDirection(0, 0, -0.1);
		}

	}
	
	class BehaviorBackwardMouseListener implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			goLocallyInThisDirection(0, 0, 0.1);
		}

	}
	
	class BehaviorLeftStepMouseListener implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			goLocallyInThisDirection(-0.1, 0, 0);
		}
		
	}
	
	class BehaviorRightStepMouseListener implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			goLocallyInThisDirection(0.1, 0, 0);
		}
		
	}
	
	class BehaviorRotationHPlusMouseListener implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			lookLocallyInThisWay(0.1, 0, 0);
		}
		
	}
	
	class BehaviorRotationHMinusMouseListener implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			lookLocallyInThisWay(-0.1, 0, 0);
		}
		
	}
	
	class BehaviorRotationPPlusMouseListener implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			lookLocallyInThisWay(0, 0.1, 0);
		}
		
	}
	
	class BehaviorRotationPMinusMouseListener implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			lookLocallyInThisWay(0, -0.1, 0);
		}
		
	}
	
	class BehaviorRotationRPlusMouseListener implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			lookLocallyInThisWay(0, 0, 0.1);
		}
		
	}
	
	class BehaviorRotationRMinusMouseListener implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent e) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			lookLocallyInThisWay(0, 0, -0.1);
		}
		
	}
	
	public void addObject3D(PObject3D obj) {
		BranchGroup branch = new BranchGroup();
		branch.addChild((TransformGroup)obj);
		scene.addChild(branch);
	}
	
	void goLocallyInThisDirection (double dx, double dy, double dz) {
		TransformGroup vpTrans;
		vpTrans = universe.getViewingPlatform().getViewPlatformTransform();
		Transform3D oldT3D = new Transform3D();
		vpTrans.getTransform(oldT3D) ;
		Vector3d translate = new Vector3d();
		translate.set(dx, dy, dz);
		Transform3D localT3D = new Transform3D();
		localT3D.setTranslation(translate);
		Transform3D newT3D = new Transform3D();
		newT3D.mul(oldT3D, localT3D);
		vpTrans.setTransform(newT3D);
	}
	
	void lookLocallyInThisWay (double h, double p, double r) {
		TransformGroup vpTrans;
		vpTrans = universe.getViewingPlatform().getViewPlatformTransform();
		Transform3D oldT3D = new Transform3D();
		vpTrans.getTransform(oldT3D);
		Vector3d rotate = new Vector3d();
		rotate.set(h, p, r);
		Transform3D localT3D = new Transform3D();
		localT3D.setEuler(rotate);
		Transform3D newT3D = new Transform3D();
		newT3D.mul (oldT3D, localT3D);
		vpTrans.setTransform (newT3D);
	}
	
}
